//! WebSocket测试

use crate::client::BinanceClientBuilder;
use crate::websocket::{WebSocketClient, StreamManager, StreamConfig, StreamType};
use crate::{Environment, ProductType};

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_websocket_client_creation() {
        let config = crate::config::BinanceConfig::new(
            "test_api_key".to_string(),
            "test_secret_key".to_string(),
            ProductType::Spot,
        );

        let ws_client = WebSocketClient::new(std::sync::Arc::new(config));
        assert!(ws_client.is_ok());
    }

    #[tokio::test]
    async fn test_websocket_client_with_proxy() {
        let config = crate::config::BinanceConfig::new(
            "test_api_key".to_string(),
            "test_secret_key".to_string(),
            ProductType::Spot,
        )
        .with_proxy(
            Some("http://127.0.0.1:8080".to_string()),
            Some("socks5://127.0.0.1:1080".to_string()),
        );

        let ws_client = WebSocketClient::new(std::sync::Arc::new(config));
        assert!(ws_client.is_ok());
    }

    #[tokio::test]
    async fn test_websocket_subscribe_ticker() {
        let mut client = BinanceClientBuilder::new(
            "test_api_key".to_string(),
            "test_secret_key".to_string(),
            ProductType::Spot,
        )
        .environment(Environment::Demo)
        .build()
        .unwrap();

        let ws_client = client.websocket().unwrap();
        let result = ws_client.subscribe_ticker("BTCUSDT").await;
        // 这里可能会失败，因为需要真实的网络连接
        assert!(result.is_ok() || result.is_err());
    }

    #[tokio::test]
    async fn test_websocket_subscribe_depth() {
        let mut client = BinanceClientBuilder::new(
            "test_api_key".to_string(),
            "test_secret_key".to_string(),
            ProductType::Spot,
        )
        .environment(Environment::Demo)
        .build()
        .unwrap();

        let ws_client = client.websocket().unwrap();
        let result = ws_client.subscribe_depth("BTCUSDT", 20).await;
        // 这里可能会失败，因为需要真实的网络连接
        assert!(result.is_ok() || result.is_err());
    }

    #[tokio::test]
    async fn test_websocket_subscribe_kline() {
        let mut client = BinanceClientBuilder::new(
            "test_api_key".to_string(),
            "test_secret_key".to_string(),
            ProductType::Spot,
        )
        .environment(Environment::Demo)
        .build()
        .unwrap();

        let ws_client = client.websocket().unwrap();
        let result = ws_client.subscribe_kline("BTCUSDT", "1m").await;
        // 这里可能会失败，因为需要真实的网络连接
        assert!(result.is_ok() || result.is_err());
    }

    #[tokio::test]
    async fn test_websocket_subscribe_trades() {
        let mut client = BinanceClientBuilder::new(
            "test_api_key".to_string(),
            "test_secret_key".to_string(),
            ProductType::Spot,
        )
        .environment(Environment::Demo)
        .build()
        .unwrap();

        let ws_client = client.websocket().unwrap();
        let result = ws_client.subscribe_trades("BTCUSDT").await;
        // 这里可能会失败，因为需要真实的网络连接
        assert!(result.is_ok() || result.is_err());
    }

    #[tokio::test]
    async fn test_websocket_subscribe_user_data() {
        let mut client = BinanceClientBuilder::new(
            "test_api_key".to_string(),
            "test_secret_key".to_string(),
            ProductType::Spot,
        )
        .environment(Environment::Demo)
        .build()
        .unwrap();

        let ws_client = client.websocket().unwrap();
        let result = ws_client.subscribe_user_data("test_listen_key").await;
        // 这里可能会失败，因为需要真实的网络连接
        assert!(result.is_ok() || result.is_err());
    }

    #[tokio::test]
    async fn test_websocket_subscribe_multiple_streams() {
        let mut client = BinanceClientBuilder::new(
            "test_api_key".to_string(),
            "test_secret_key".to_string(),
            ProductType::Spot,
        )
        .environment(Environment::Demo)
        .build()
        .unwrap();

        let ws_client = client.websocket().unwrap();
        let streams = vec![
            "btcusdt@ticker".to_string(),
            "btcusdt@depth20".to_string(),
            "btcusdt@kline_1m".to_string(),
        ];
        let result = ws_client.subscribe_multiple_streams(&streams).await;
        // 这里可能会失败，因为需要真实的网络连接
        assert!(result.is_ok() || result.is_err());
    }

    #[tokio::test]
    async fn test_websocket_unsubscribe() {
        let mut client = BinanceClientBuilder::new(
            "test_api_key".to_string(),
            "test_secret_key".to_string(),
            ProductType::Spot,
        )
        .environment(Environment::Demo)
        .build()
        .unwrap();

        let ws_client = client.websocket().unwrap();
        let result = ws_client.unsubscribe("btcusdt@ticker").await;
        // 这里可能会失败，因为需要真实的网络连接
        assert!(result.is_ok() || result.is_err());
    }

    #[tokio::test]
    async fn test_websocket_close() {
        let mut client = BinanceClientBuilder::new(
            "test_api_key".to_string(),
            "test_secret_key".to_string(),
            ProductType::Spot,
        )
        .environment(Environment::Demo)
        .build()
        .unwrap();

        let ws_client = client.websocket().unwrap();
        let result = ws_client.close().await;
        // 这里可能会失败，因为需要真实的网络连接
        assert!(result.is_ok() || result.is_err());
    }

    #[test]
    fn test_stream_manager() {
        let mut manager = StreamManager::new();

        // 添加流
        let config = StreamConfig::ticker("BTCUSDT");
        let stream_name = manager.add_stream(config);
        assert_eq!(stream_name, "btcusdt@ticker");

        // 获取所有流
        let streams = manager.get_all_streams();
        assert_eq!(streams.len(), 1);
        assert_eq!(streams[0], "btcusdt@ticker");

        // 获取流配置
        let config = manager.get_stream_config("btcusdt@ticker");
        assert!(config.is_some());
        assert_eq!(config.unwrap().symbol, "BTCUSDT");

        // 移除流
        let removed_config = manager.remove_stream("btcusdt@ticker");
        assert!(removed_config.is_some());
        assert_eq!(removed_config.unwrap().symbol, "BTCUSDT");

        // 验证流已移除
        let streams = manager.get_all_streams();
        assert_eq!(streams.len(), 0);
    }

    #[test]
    fn test_stream_config() {
        // 测试实时价格流配置
        let ticker_config = StreamConfig::ticker("BTCUSDT");
        assert_eq!(ticker_config.stream_type, StreamType::Ticker);
        assert_eq!(ticker_config.symbol, "BTCUSDT");

        // 测试订单簿流配置
        let depth_config = StreamConfig::depth("BTCUSDT", 20);
        assert_eq!(depth_config.stream_type, StreamType::Depth);
        assert_eq!(depth_config.symbol, "BTCUSDT");
        assert_eq!(depth_config.levels, Some(20));

        // 测试K线流配置
        let kline_config = StreamConfig::kline("BTCUSDT", "1m");
        assert_eq!(kline_config.stream_type, StreamType::Kline);
        assert_eq!(kline_config.symbol, "BTCUSDT");
        assert_eq!(kline_config.interval, Some("1m".to_string()));

        // 测试交易流配置
        let trade_config = StreamConfig::trade("BTCUSDT");
        assert_eq!(trade_config.stream_type, StreamType::Trade);
        assert_eq!(trade_config.symbol, "BTCUSDT");

        // 测试用户数据流配置
        let user_data_config = StreamConfig::user_data("test_listen_key");
        assert_eq!(user_data_config.stream_type, StreamType::UserData);
        assert_eq!(user_data_config.listen_key, Some("test_listen_key".to_string()));
    }

    #[test]
    fn test_stream_utils() {
        use crate::websocket::streams::StreamUtils;

        // 测试流名称解析
        let config = StreamUtils::parse_stream_name("btcusdt@ticker");
        assert!(config.is_ok());
        let config = config.unwrap();
        assert_eq!(config.symbol, "btcusdt");
        assert_eq!(config.stream_type, StreamType::Ticker);

        // 测试流名称验证
        assert!(StreamUtils::validate_stream_name("btcusdt@ticker"));
        assert!(StreamUtils::validate_stream_name("btcusdt@depth20"));
        assert!(StreamUtils::validate_stream_name("btcusdt@kline_1m"));
        assert!(!StreamUtils::validate_stream_name("invalid_stream"));

        // 测试组合流URL构建
        let streams = vec![
            "btcusdt@ticker".to_string(),
            "btcusdt@depth20".to_string(),
        ];
        let url = StreamUtils::build_combined_stream_url(&streams);
        assert_eq!(url, "btcusdt@ticker/btcusdt@depth20");
    }
}
